﻿using AutoMapper;
using QYmall.Core.Common.Emum;
using QYmall.Core.Common.Extensions;
using QYmall.Core.Common.Helper;
using QYmall.Core.DBFactory.Database;
using QYmall.Core.IServices;
using QYmall.Core.Model.Models;
using QYmall.Core.Model.ViewModels;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace QYmall.Core.Services
{
    /// <summary>
    /// 商户信息接口实现
    /// </summary>
    public class MerchantService : BaseService, IMerchantService
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly UserManager<ApplicationUser> _userManager;
        private readonly RoleManager<ApplicationRole> _roleManager;
        private readonly IMapper _mapper;
        public MerchantService(IDbContextFactory contentFactory,
            UserManager<ApplicationUser> userManager,
            RoleManager<ApplicationRole> roleManager,
            IHttpContextAccessor httpContextAccessor,
            IMapper mapper) : base(contentFactory)
        {
            _httpContextAccessor = httpContextAccessor;
            _userManager = userManager;
            _roleManager = roleManager;
            _mapper = mapper;
        }

        /// <summary>
        /// 获取商户信息
        /// </summary>
        public async Task<Merchants?> QueryAsync(Expression<Func<Merchants, bool>> funcWhere, WriteRoRead writeAndRead = WriteRoRead.Read)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库

            var result = await _context.Set<Merchants>()
                .Include(x => x.User)
                .Include(x=>x.Category)
                .Include(x => x.Store).FirstOrDefaultAsync(funcWhere);
            return result;
        }

        /// <summary>
        /// 根据条件获取列表
        /// </summary>
        public async Task<IEnumerable<Merchants>> QueryListAsync(int top, Expression<Func<Merchants, bool>> funcWhere,
            string orderBy, WriteRoRead writeAndRead = WriteRoRead.Read)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库

            var result = _context.Set<Merchants>()
                .Include(x => x.User)
                .Include(x => x.Category)
                .Include(x => x.Store).Where(funcWhere);//条件筛选
            result = result.OrderByBatch(orderBy);//调用Linq扩展类排序
            if (top > 0) result = result.Take(top);//等于0显示所有数据
            return await result.ToListAsync();
        }

        /// <summary>
        /// 根据条件获取分页列表
        /// </summary>
        public async Task<PaginationList<Merchants>> QueryPageAsync(int pageSize, int pageIndex, Expression<Func<Merchants, bool>> funcWhere,
            string orderBy, WriteRoRead writeAndRead = WriteRoRead.Read)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库

            var result = _context.Set<Merchants>()
                .Include(x => x.User)
                .Include(x => x.Category)
                .Include(x => x.Store).Where(funcWhere);//条件筛选
            result = result.OrderByBatch(orderBy);//调用Linq扩展类排序
            return await PaginationList<Merchants>.CreateAsync(pageIndex, pageSize, result);
        }

        /// <summary>
        /// 根据条件获取分页列表(含商品)
        /// </summary>
        public async Task<PaginationList<MerchantsGoodsClientDto>> QueryGoodsPageAsync(int top, int pageSize, int pageIndex, Expression<Func<Merchants, bool>> funcWhere,
            string orderBy, WriteRoRead writeAndRead = WriteRoRead.Read)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库

            //构造查询表达式
            var query = _context.Set<Merchants>()
                .Where(funcWhere)
                .OrderByBatch(orderBy)
                .Select(m => new
                {
                    Merchant = m,
                    ShopGoods = _context.Set<ShopGoods>()
                        .Where(g => g.MerchantId == m.Id)
                        .Take(top)
                        .ToList()
                })
                .Select(mg=> new MerchantsGoodsClientDto
                {
                    Id = mg.Merchant.Id,
                    Title = mg.Merchant.Title,
                    Avatar = mg.Merchant.Avatar,
                    IsSelf = mg.Merchant.IsSelf,
                    FavoriteCount = mg.Merchant.FavoriteCount,
                    ShopGoods = mg.ShopGoods.Select(x => new ShopGoodsClientDto
                    {
                        Id = x.Id,
                        Title = x.Title,
                        Zhaiyao = x.Zhaiyao,
                        ImgUrl = x.ImgUrl,
                        MarketPrice=x.MarketPrice,
                        SellPrice = x.SellPrice
                    })
                });
            return await PaginationList<MerchantsGoodsClientDto>.CreateAsync(pageIndex, pageSize, query);
        }

        /// <summary>
        /// 获取记录总数量
        /// </summary>
        public async Task<int> QueryCountAsync(Expression<Func<Merchants, bool>> funcWhere, WriteRoRead writeAndRead = WriteRoRead.Read)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库

            return await _context.Set<Merchants>().Include(x => x.User).Where(funcWhere).CountAsync();
        }

        /// <summary>
        /// 添加记录
        /// </summary>
        public async Task<MerchantsDto> AddAsync(MerchantsEditDto modelDto, WriteRoRead writeAndRead = WriteRoRead.Write)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库
            //检查会员是否存在
            var memberModel = await _context.Set<Members>().FirstOrDefaultAsync(x => x.UserId == modelDto.UserId);
            if (memberModel == null)
            {
                throw new ResponseException("会员账户不存在或已删除");
            }
            //检查商户分类是否存在
            var category = await _context.Set<MerchantCategory>().FirstOrDefaultAsync(x => x.Id == modelDto.CategoryId);
            if (category == null)
            {
                throw new ResponseException("商户分类不存在或已删除");
            }
            //检查店铺类型是否存在
            if (await _context.Set<MerchantStore>().FirstOrDefaultAsync(x => x.Id == modelDto.StoreId) == null)
            {
                throw new ResponseException("店铺类型不存在或已删除");
            }

            //映射成实体
            var model = _mapper.Map<Merchants>(modelDto);
            //如果NULL则使用分类的交易费比例
            if (modelDto.TradeFee == null)
            {
                model.TradeFee = category.TradeFee;
            }
            await _context.Set<Merchants>().AddAsync(model);
            await this.SaveAsync();

            //映射成DTO
            var result = _mapper.Map<MerchantsDto>(model);
            return result;
        }

        /// <summary>
        /// 修改记录
        /// </summary>
        public async Task<bool> UpdateAsync(int id, MerchantsBaseDto modelDto, WriteRoRead writeAndRead = WriteRoRead.Write)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库

            //根据ID获取记录
            var model = await _context.Set<Merchants>().Where(x => x.Id == id).FirstOrDefaultAsync();
            //如果不存在则抛出异常
            if (model == null)
            {
                throw new ResponseException("数据不存在或已删除", ErrorCode.NotFound, StatusCodes.Status404NotFound);
            }
            //检查商户分类是否存在
            var category = await _context.Set<MerchantCategory>().FirstOrDefaultAsync(x => x.Id == modelDto.CategoryId);
            if (category == null)
            {
                throw new ResponseException("商户分类不存在或已删除");
            }
            //检查店铺类型是否存在
            if (await _context.Set<MerchantStore>().FirstOrDefaultAsync(x => x.Id == modelDto.StoreId) == null)
            {
                throw new ResponseException("店铺类型不存在或已删除");
            }
            //将DTO映射到源数据
            var mapModel = _mapper.Map(modelDto, model);
            _context.Set<Merchants>().Update(mapModel);
            return await this.SaveAsync();
        }
    }
}
